var express = require('express')
var router = express.Router()
var fs = require('fs')
var multiparty = require('multiparty')
require('shelljs/global')
var qiniu = require('../util/qiniu')
var leancloud = require('../util/leancloud')
var bsdiff = require('../util/bsdiff')

/**
 * 文件上传
 */
router.post('/upload', function (req, res, next) {
    var form = new multiparty.Form()
    fs.exists('uploads/',
        exist => {
            if (!exist) {
                fs.mkdir('uploads/')
            }
        }
    );
    form.uploadDir = 'uploads/'
    form.maxFilesSize = 200 * 1024 * 1024
    form.parse(req, function (err, fields, files) {
        const ret = {}
        if (err != null) {
            ret.msg = err.message
            ret.result = 'error'
        } else {
            ret.data = files.file[0].path
            ret.msg = ''
            ret.result = 'success'
        }
        res.end(JSON.stringify(ret))
    })
})

/**
 * 保存差分信息到leancloud
 */
router.post('/savePatch', async function (req, res, next) {
    if (req.body.patch) {
        try {
            var key = Number(new Date())
            let uploadFileResp = await qiniu.uploadFileNew(
                req.body.patch,
                `patch/${key}`,
                qiniu.uploadToken());
            let domain = await qiniu.getFileDomain();
            let result = await leancloud.saveObject({
                    VersionName: req.body.versionName || '',
                    VersionCode: req.body.versionCode || '',
                    FromVersionName: req.body.fromVersionName || '',
                    FromVersionCode: req.body.fromVersionCode || '',
                    AppType: req.body.appType || '',
                    BuildType: req.body.buildType || '',
                    IsPatch: req.body.isPatch || false,
                    DownloadUrl: `http://${domain}/patch/${key}`
                },
                'Version'
            );
            res.send({
                result: 'success',
                msg: '',
                data: ''
            })
        } catch (err) {
            res.send({
                result: 'error',
                msg: err.message
            })
        }
    } else {
        res.send({
            result: 'error',
            msg: 'patch cannot be null'
        })
    }

})

/**
 * 查询应用类型
 */
router.get('/appTypes', function (req, res, next) {
    leancloud
        .queryAll('AppType')
        .then(data => {
            const ret = []
            console.log(data)
            data.forEach(d => {
                console.log(d.get('name'))
                ret.push(d.get('name'))
            })
            console.log(ret)
            res.send({
                result: 'success',
                msg: '',
                data: ret
            })
        })
        .catch(err => {
            res.send({
                result: 'error',
                msg: err.message,
                data: ''
            })
        })
})

/**
 * 新旧文件进行差分
 */
router.post('/diff', function (req, res, next) {
    fs.exists('patch/'),
        exist => {
            if (!exist) {
                fs.mkdir('patch/')
            }
        }
    console.log(req.body)
    var timetamp4 = Number(new Date())
    exec(
        `bsdiff.exe ${req.body.originFile} ${
      req.body.newFile
    } patch/${timetamp4}.patch`,
        function (code, stdout, stderr) {
            console.log('Exit code:', code)
            console.log('Program output:', stdout)
            console.log('Program stderr:', stderr)
            if (code == 0) {
                res.end(
                    JSON.stringify({
                        result: 'success',
                        msg: '',
                        data: `patch/${timetamp4}.patch`
                    })
                )
            } else {
                res.end(
                    JSON.stringify({
                        result: 'error',
                        msg: stderr,
                        data: ''
                    })
                )
            }
        }
    )
    //    const child =  exec('bsdiff.exe '+'uploads/_sdL8RcHn2zAqIf-SkrZbc8j.apk' + ' uploads/XxD6X1J1B27OYp601vYD1xa5.apk'+ ' uploads/patch',{async:true})
    //     child.stdout.on('data', function(data) {
    //         /* ... do something with data ... */
    //         console.log(data)
    //       });
    //       child1.stdout.on('data', function(data) {
    //         /* ... do something with data ... */
    //         console.log(data)
    //       });
})

/**
 * 添加应用类型
 */
router.post('/addAppType', function (req, res, next) {
    leancloud.queryOption({
        name: req.body.name
    }, "AppType").then((data) => {
        if (data.length == 0) {
            leancloud.saveObject({
                name: req.body.name
            }, "AppType").then((data) => {
                res.send({
                    result: 'success',
                    msg: '',
                    data: ''
                })
            }).catch((err) => {
                res.send({
                    result: 'error',
                    msg: err.message,
                    data: ''
                })
            })
        } else {
            res.send({
                result: 'error',
                msg: '"' + req.body.name + '"类型已存在',
                data: ''
            })
        }
    }).catch(err => {
        res.send({
            result: 'error',
            msg: err.message,
            data: ''
        })
    })
})

/*
查询apk版本
 */
router.get('/versions', function (req, res, next) {
    const option = {}
    if (req.query.appType) {
        option['AppType'] = req.query.appType
    }
    if (req.query.buildType) {
        option['BuildType'] = req.query.buildType
    }
    if (req.query.published) {
        option['IsPublished'] = req.query.published === 'true'
    }
    console.log(option)
    leancloud.queryOptionPage(option, {
        order: 'DESC',
        sort: 'VersionCode',
        pageIndex: req.query.pageIndex || 0,
        pageSize: req.query.pageSize || 10
    }, 'ApkVersion').then(data => {
        const ret = []
        data.forEach(d => {
            ret.push(d)
        })
        res.send({
            result: 'success',
            msg: '',
            data: ret
        })
    }).catch(err => {
        res.send({
            result: 'error',
            msg: err.message,
            data: ''
        })
    })
})

/**
 * 发布升级
 */
router.post('/publishVersion', async function (req, res, next) {
    try {
        if (!req.body.appType) {
            throw new Error("appType 不能为空")
        }
        if (!req.body.buildType) {
            throw new Error("buildType 不能为空")
        }
        if (!req.body.versionName) {
            throw new Error("versionName 不能为空")
        }
        if (!req.body.versionCode) {
            throw new Error("versionCode 不能为空")
        }
        if (req.body.isPatch) {
            // 差分处理
            if (!req.body.FromVersionCode || !req.body.FromVersionName || !req.body.fromDownloadUrl || !req.body.downloadUrl) {
                throw new Error("缺少差分版本信息")
            }
            const queryOption = {
                AppType: req.body.appType,
                BuildType: req.body.buildType,
                VersionCode: req.body.versionCode,
                VersionName: req.body.versionName,
                FromVersionCode: req.body.FromVersionCode,
                FromVersionName: req.body.FromVersionName,
                IsPatch: true
            }
            let queryResult = await leancloud.queryOption(queryOption, 'Version');
            if (queryResult.length > 0) {
                throw new Error('升级信息已存在')
            }
            var file1 = 'uploads/file1'
            var file2 = 'uploads/file2'
            if (fs.existsSync(file1)) {
                fs.unlinkSync(file1)
            }
            if (fs.existsSync(file2)) {
                fs.unlinkSync(file2)
            }

            var task1 = qiniu.downloadFile(req.body.fromDownloadUrl, file1)
            var task2 = qiniu.downloadFile(req.body.downloadUrl, file2)
            await Promise.all([task1, task2])
            console.log('after file download')
            var patchfile = await bsdiff.diff(file1, file2)
            var key = Number(new Date())
            console.log('after file download')
            let uploadFileResp = await qiniu.uploadFileNew(
                patchfile,
                `patch/${key}`,
                qiniu.uploadToken());
            let domain = await qiniu.getFileDomain();
            queryOption['DownloadUrl'] = `http://${domain}/patch/${key}`
            if (req.body.isForce) {
                queryOption['IsForce'] = req.body.isForce
            }
            await leancloud.saveObject(queryOption, 'Version');
            res.send({
                result: 'success',
                msg: '',
                data: ''
            })
        } else {
            if (!req.body.downloadUrl) {
                throw new Error("downloadUrl 不能为空")
            }
            const queryOption = {
                AppType: req.body.appType,
                BuildType: req.body.buildType,
                VersionCode: req.body.versionCode,
                VersionName: req.body.versionName,
                IsPatch: false
            }
            if (req.body.FromVersionCode) {
                queryOption['FromVersionCode'] = req.body.FromVersionCode
            }
            if (req.body.FromVersionName) {
                queryOption['FromVersionName'] = req.body.FromVersionName
            }
            // 查询版本是否已存在
            let queryResult = await leancloud.queryOption(queryOption, 'Version');
            if (queryResult.length > 0) {
                throw new Error('升级信息已存在')
            }
            if (req.body.isForce) {
                queryOption['IsForce'] = req.body.isForce
            }
            queryOption['DownloadUrl'] = req.body.downloadUrl
            await leancloud.saveObject(queryOption, 'Version');
            if (req.body.objectId) {
                await leancloud.updateObject({
                    objectId: req.body.objectId,
                    IsPublished: true
                }, 'ApkVersion');
            }
            res.send({
                result: 'success',
                msg: '',
                data: ''
            })
        }
    } catch (err) {
        res.send({
            result: 'error',
            msg: err.message
        })
    }
})

/**
 * 批量查询更新配置
 */
router.post('/updates', async function (req, res) {
    const option = {},
        pageOption = {};
    try {
        if (!req.body.appType) {
            throw new Error('appType 不能为空')
        }
        if (!req.body.buildType) {
            throw new Error('buildType 不能为空')
        }
        option['AppType'] = req.body.appType;
        option['BuildType'] = req.body.buildType;
        pageOption['pageSize'] = req.body.pageSize || 10;
        pageOption['pageIndex'] = req.body.pageIndex || 0;
        pageOption['sort'] = 'createdAt'
        pageOption['order'] = 'DESC'
        let ret = await leancloud.queryOptionPage(option, pageOption, 'Version');
        res.send({
            result: 'success',
            msg: '',
            data: ret
        })
    } catch (err) {
        res.send({
            result: 'error',
            msg: err.message
        })
    }
})

/**
 * 添加版本
 */
router.post('/addVersion', function (req, res, next) {
    var form = new multiparty.Form()
    fs.exists('uploads/',
        exist => {
            if (!exist) {
                fs.mkdir('uploads/')
            }
        }
    );
    form.uploadDir = 'uploads/'
    form.maxFilesSize = 200 * 1024 * 1024
    form.parse(req, async function (err, fields, files) {
        if (err) {
            res.send({
                result: 'error',
                msg: err.message,
                data: ''
            })
        } else {
            try {
                let queryResult = await leancloud.queryOption({
                    AppType: fields.appType[0],
                    BuildType: fields.buildType[0],
                    VersionCode: fields.versionCode[0],
                    VersionName: fields.versionName[0],
                }, 'ApkVersion');
                if (queryResult.length > 0) {
                    throw new Error('版本已存在')
                }
                var key = Number(new Date())
                await qiniu.uploadFileNew(
                    files.file[0].path,
                    `apk/${key}.apk`,
                    qiniu.uploadToken());
                let domain = await qiniu.getFileDomain();
                let saveData = await leancloud.saveObject({
                    AppType: fields.appType[0],
                    BuildType: fields.buildType[0],
                    VersionCode: fields.versionCode[0],
                    VersionName: fields.versionName[0],
                    DownloadUrl: `http://${domain}/apk/${key}.apk`
                }, 'ApkVersion');
                res.send({
                    result: 'success',
                    msg: '',
                    data: saveData
                })
            } catch (err) {
                res.send({
                    result: 'error',
                    msg: err.message,
                    data: ''
                })
            }
        }
    })
})

router.get('/test', function (req, res, next) {
    var key = Number(new Date())
    //    qiniu.uploadFile('patch/1533777480615',`patch/${key}`,qiniu.uploadToken(),(err,resp)=>{
    //         res.send({
    //             err,resp
    //         })
    //    })
    // qiniu.fileList({},(err,resp)=>{
    //     res.send({
    //         err,resp
    //     })
    // })
    // leancloud.saveObject({
    //     VersionName:'1.0.0',
    //     VersionCode:'VersionCode',
    //     FromVersionName:'0.1.0',
    //     FromVersionCode:'FromVersionCode',
    //     AppType:'dsada',
    //     BuildType:'develop'
    // },'Version').then((data)=>{
    //     console.log(data);
    // }).catch(err=>{
    //     console.log(err)
    // })
    leancloud
        .queryVersion('1.3.2', '2018072717', '互助商城', 'develop')
        .then(data => {
            console.log(data)
        })
        .catch(err => {
            console.log(err)
        })
    qiniu.getFileDomain().then(domain => {
        qiniu.fileState('patch/1533782343964', (err, resp) => {
            res.send({
                err,
                resp,
                domain
            })
        })
    })
})

/**
 * 差分合并测试
 */
router.post('/patch', function (req, res, next) {
    fs.exists('patch/'),
        exist => {
            if (!exist) {
                fs.mkdir('patch/')
            }
        }
    console.log(req.body)
    var timetamp4 = Number(new Date())
    exec(
        `bspatch.exe ${req.body.originFile} patch/${timetamp4}.patch ${
      req.body.patchFile
    }`,
        async function (code, stdout, stderr) {
            console.log('Exit code:', code)
            console.log('Program output:', stdout)
            console.log('Program stderr:', stderr)
            if (code == 0) {
                const md5Tasks = []
                md5Tasks.push(getFileMd5(req.body.newFile))
                md5Tasks.push(getFileMd5(`patch/${timetamp4}.patch`))
                const resp = await Promise.all(md5Tasks)
                if (resp[0] == resp[1]) {
                    res.end(
                        JSON.stringify({
                            result: 'success',
                            msg: ''
                        })
                    )
                } else {
                    res.end(
                        JSON.stringify({
                            result: 'error',
                            msg: ''
                        })
                    )
                }
            } else {
                res.end(
                    JSON.stringify({
                        result: 'error',
                        msg: stderr,
                        data: ''
                    })
                )
            }
        }
    )
})

var crypto = require('crypto')
var fs = require('fs')

/**
 * 计算文件md5
 * @param {} file1
 */
const getFileMd5 = file1 => {
    return new Promise((reslove, reject) => {
        var rs = fs.createReadStream(file1)

        var hash = crypto.createHash('md5')
        rs.on('data', hash.update.bind(hash))

        rs.on('end', function () {
            reslove(hash.digest('hex'))
        })
    })
}

module.exports = router
